package com.xiaoxin.experience.util;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 并发工具类
 * @author xiaoxin
 */
@Slf4j
public class ConcurrentUtil
{

    private static final ExecutorService executorService = Executors.newCachedThreadPool();

    /**
     * 模拟并发
     * @param run 要进行的并发操作
     * @param clientTotal 请求总数
     * @param threadTotal 并发的线程数
     */
    public static void simulateConcurrency(Runnable run, int clientTotal, int threadTotal)
    {

        //信号量，此处用于控制并发的线程数
        final Semaphore semaphore = new Semaphore(threadTotal);

        //闭锁，可实现计数器递减
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal ; i++)
        {
            executorService.execute(() -> {
                try
                {
                    //执行此方法用于获取执行许可，当总计未释放的许可数不超过200时，
                    //允许通行，否则线程阻塞等待，直到获取到许可。
                    semaphore.acquire();
                    run.run();
                    //释放许可
                    semaphore.release();
                }
                catch (Exception e)
                {
                   log.error("execute task run fail ", e);
                }
                //闭锁减一
                countDownLatch.countDown();
            });
        }
        try
        {
            //线程阻塞，直到闭锁值为0时，阻塞才释放，继续往下执行
            countDownLatch.await();
        }
        catch (Exception e)
        {
            log.error("wait task run finish fail",e);
        }
    }
}
